package com.baizhi.lucene.luceneImpl;

import com.baizhi.dao.AtricleDao;
import com.baizhi.entity.Article;
import com.baizhi.lucene.LuceneService;
import com.baizhi.util.LuceneUtil;
import org.apache.lucene.document.*;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.FSDirectory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2019/4/16.
 */
@Component
public class LuceneServiceImpl implements LuceneService {
    @Autowired
    private AtricleDao atricleDao;

    /**
     * 批量添加索引
     * @param articles
     * @return
     */
    @Override
    public int addIndexs(List<Article> articles) {
        for (Article article : articles) {
            System.out.println(article);
            Document document = new Document();
            document.add(new IntField("articleId",article.getArticleId(), Field.Store.YES));
            document.add(new TextField("articleName",article.getArticleName(), Field.Store.YES));
            document.add(new StringField("gurnName",article.getGurnName(), Field.Store.YES));
            document.add(new TextField("articleCount",article.getArticleCount(), Field.Store.YES));
            //创建索引
            IndexWriter indexWriter = LuceneUtil.getIndexWriter();
            try {
                //将数据交给索引管理
                indexWriter.addDocument(document);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                LuceneUtil.commit(indexWriter);
            }
        }

        return 0;
    }


    /**
     * 单个添加索引
     * @param article
     * @return
     * @throws IOException
     */
    @Override
    public boolean addIndexOne(Article article) throws IOException {
        // 创建索引 （分词器版本号、索引保存路径在工具类中已经设置，）
        IndexWriter indexWriter = LuceneUtil.getIndexWriter();
        try {
//        3. 扫描文章（把原始数据提交给Lucene  把原始数据封装在document对象中）
            Document document = new Document();
            document.add(new IntField("articleId",article.getArticleId(), Field.Store.YES));
            document.add(new TextField("articleName",article.getArticleName(), Field.Store.YES));
            document.add(new StringField("gurnName",article.getGurnName(), Field.Store.YES));
            document.add(new TextField("articleCount",article.getArticleCount(), Field.Store.YES));

            //4.3把要写出的数据 给 indexWriter对象
            indexWriter.addDocument(document);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return  false;
        }finally {
            LuceneUtil.commit(indexWriter);

        }
    }


    /**
     * 删除所有的索引
     * @return
     */
    @Override
    public boolean deleteAllIndex() {
        IndexWriter indexWriter = LuceneUtil.getIndexWriter();
        try {
            indexWriter.deleteAll();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return  false;
        }finally {
            LuceneUtil.commit(indexWriter);
        }

    };


    /**
     * 删除指定文章的索引
     * @param article
     * @return
     */
    @Override
    public boolean deleteOne(Article article) {
        IndexWriter indexWriter=LuceneUtil.getIndexWriter();
        //删除需要根据id指定准确唯一的索引删除
        Term term=new Term("articleId",article.getArticleId().toString());
        try {
            indexWriter.deleteDocuments(term);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }finally {
            LuceneUtil.commit(indexWriter);
        }
    }


    @Override
    public boolean updateOne(Article article) {
        IndexWriter indexWriter=LuceneUtil.getIndexWriter();
        Document document = new Document();
        document.add(new IntField("articleId",article.getArticleId(), Field.Store.YES));
        document.add(new TextField("articleName",article.getArticleName(), Field.Store.YES));
        document.add(new TextField("articleContent",article.getArticleCount(), Field.Store.YES));
        document.add(new TextField("gurnName",article.getGurnName(), Field.Store.YES));
        try {
            indexWriter.updateDocument(new Term("articleId","1"),document);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;

        }finally {
            LuceneUtil.commit(indexWriter);
        }
    }


    @Override
    public List<Article> queryByKeyword(String keyword) {
        SimpleHTMLFormatter htmlFormatter = new SimpleHTMLFormatter("<font color='red'>","</font>");
        Query query = LuceneUtil.getQuery(keyword);
        /**
         * 2.获取分词结果
         *  通过QueryScorer对象 处理分词结果
         */
        QueryScorer queryScorer = new QueryScorer(query);
        /**
         * 3.创建高亮器
         */
        Highlighter highlighter = new Highlighter(htmlFormatter,queryScorer);

        List<Article> articles=new ArrayList<>();
//        3. 读取索引文件
        FSDirectory directory = null;
        try {
            directory = FSDirectory.open(new File("D://LuceneTest"));
            DirectoryReader reader = DirectoryReader.open(directory);
            //4. 使用索引检索
            IndexSearcher indexSearcher = new IndexSearcher(reader);
            /**
             * search方法
             * 1.query对象  封装了搜索关键词
             * 2.你想要查询多少条  最大展示条数  和结果没有必然的联系
             *
             * TopDocs 封装了所有结果的相关信息
             */
            TopDocs topDocs = indexSearcher.search(query, 100);
            /**
             * ScoreDoc中保存了两项内容
             * score 分数
             * doc 文档对象的编号
             */
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            for (ScoreDoc scoreDoc : scoreDocs) {
//          5. 获取索引中的位置信息
                int docId = scoreDoc.doc;
//          6. 通过document对象id 获取对应的对象 document对象中封装了我们的数据
                Document document = indexSearcher.doc(docId);
                System.out.println(document.get("articleId")+"0000000");
                System.out.println(document.get("articleName")+"0000000000");
                Article article=new Article();

                Integer id= Integer.valueOf(document.get("articleId"));
                String articleId = highlighter.getBestFragment(LuceneUtil.analyzer, "articleId", document.get("articleId"));

                article.setArticleId(id) ;
                String articleName = highlighter.getBestFragment(LuceneUtil.analyzer, "articleName", document.get("articleName"));
                article.setArticleName(articleName);
                String articleCount = highlighter.getBestFragment(LuceneUtil.analyzer, "articleCount", document.get("articleCount"));
                article.setArticleCount(articleCount);
                String gurnName = highlighter.getBestFragment(LuceneUtil.analyzer, "gurnName", document.get("gurnName"));
                article.setGurnName(gurnName);
                articles.add(article);
            }
            return articles;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidTokenOffsetsException e) {
            e.printStackTrace();
            return null;
        }
    }


    @Override
    public Map resetIndexDB() {
        Map map=new HashMap();
        try {
            deleteAllIndex();
            List<Article> articles = atricleDao.selectAllAriticleLucene();
            addIndexs(articles);
            map.put("isok",true);
            return  map;
        } catch (Exception e) {
            e.printStackTrace();
            map.put("isok",false);
            return map;

        }
    }
}
